package importer;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.zip.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import data.Image;
import database.DataDAO;
import database.Database;
import database.UsersDAO;

public class DataImporter {

	private File xmlFile;
	private Document DOM;
	private Database db;
	private DataDAO dataDAO;
	private UsersDAO usersDAO;
	int projectID, fieldID, imageID, recordID, recordValueID, numOfFields;

	public DataImporter(String fileURL) throws ClassNotFoundException, SQLException {
		xmlFile = new File(fileURL);
		Database.initialize();
		db = new Database();
		dataDAO = db.getDataDAO();
		usersDAO = db.getUsersDAO();
	}

	public static void main(String args[]) throws ParserConfigurationException,
			SAXException, IOException, ClassNotFoundException, SQLException {
		DataImporter di = new DataImporter(args[0]);
		di.createDOM();
		di.parseDOM();
	}

	public void createDOM() throws ParserConfigurationException, SAXException,
			IOException {
		DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
		DOM = docBuilder.parse(xmlFile);
	}

	private void parseUser(Node prevNode) {
		NodeList nodeList = prevNode.getChildNodes();
		String username = null, password = null, firstName = null, lastName = null, email = null;
		int indexedRecords = 0;
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node currentNode = nodeList.item(i);
			String check = currentNode.getNodeName();

			if (check.equals("username")) {
				username = currentNode.getChildNodes().item(0).getNodeValue();
			} else if (check.equals("password")) {
				password = currentNode.getChildNodes().item(0).getNodeValue();
			} else if (check.equals("firstname")) {
				firstName = currentNode.getChildNodes().item(0).getNodeValue();
			} else if (check.equals("lastname")) {
				lastName = currentNode.getChildNodes().item(0).getNodeValue();
			} else if (check.equals("email")) {
				email = currentNode.getChildNodes().item(0).getNodeValue();
			} else if (check.equals("indexedrecords")) {
				indexedRecords = Integer.parseInt(currentNode.getChildNodes()
						.item(0).getNodeValue());
			}
		}
		usersDAO.createUser(username, password, firstName, lastName, email,
				indexedRecords);
	}

	private void parseValues(Node prevNode) throws SQLException {
		NodeList nodeList = prevNode.getChildNodes();
		ArrayList<String> list = new ArrayList<String>();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node currentNode = nodeList.item(i);
			String check = currentNode.getNodeName();
			if (check.equals("value")) {
				list.add(currentNode.getChildNodes().item(0).getNodeValue());
			}
		}

		for (String str : list) {
			recordValueID++;
			dataDAO.createRecordValue(recordValueID, str, recordID, fieldID);
		}
	}

	private void parseRecords(Node prevNode) throws SQLException {
		NodeList nodeList = prevNode.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node currentNode = nodeList.item(i);
			String check = currentNode.getNodeName();
			if (check.equals("values")) {
				parseValues(currentNode);
			}
		}
		dataDAO.createRecord(recordID, imageID);
	}

	private void parseImages(Node prevNode) throws SQLException {
		NodeList nodeList = prevNode.getChildNodes();
		String file = null;
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node currentNode = nodeList.item(i);
			String check = currentNode.getNodeName();

			if (check.equals("file")) {
				file = currentNode.getChildNodes().item(0).getNodeValue();
			} else if (check.equals("records")) {
				doParse(currentNode);
			}
		}
		dataDAO.createImage(imageID, projectID, file);
	}

	private void parseFields(Node prevNode) throws SQLException {
		NodeList nodeList = prevNode.getChildNodes();
		String title = null, helphtml = null, knowndata = null;
		int xCoord = 0, width = 0;

		for (int i = 0; i < nodeList.getLength(); i++) {
			Node currentNode = nodeList.item(i);
			String check = currentNode.getNodeName();

			if (check.equals("title")) {
				title = currentNode.getChildNodes().item(0).getNodeValue();
			} else if (check.equals("xcoord")) {
				xCoord = Integer.parseInt(currentNode.getChildNodes().item(0)
						.getNodeValue());
			} else if (check.equals("width")) {
				width = Integer.parseInt(currentNode.getChildNodes().item(0)
						.getNodeValue());
			} else if (check.equals("helphtml")) {
				helphtml = currentNode.getChildNodes().item(0).getNodeValue();
			} else if (check.equals("knowndata")) {
				knowndata = currentNode.getChildNodes().item(0).getNodeValue();
			}
		}
		numOfFields++;
		dataDAO.createField(fieldID, projectID, title, xCoord, width, helphtml);
	}

	private void parseProjects(Node prevNode) throws SQLException {
		NodeList nodeList = prevNode.getChildNodes();
		String title = null;
		int recordsPerImage = 0, firstYCoord = 0, recordHeight = 0;

		for (int i = 0; i < nodeList.getLength(); i++) {
			Node currentNode = nodeList.item(i);
			String check = currentNode.getNodeName();

			if (check.equals("title")) {
				title = currentNode.getChildNodes().item(0).getNodeValue();
			} else if (check.equals("recordsperimage")) {
				recordsPerImage = Integer.parseInt(currentNode.getChildNodes()
						.item(0).getNodeValue());
			} else if (check.equals("firstycoord")) {
				firstYCoord = Integer.parseInt(currentNode.getChildNodes()
						.item(0).getNodeValue());
			} else if (check.equals("recordheight")) {
				recordHeight = Integer.parseInt(currentNode.getChildNodes()
						.item(0).getNodeValue());
			} else if (check.equals("fields")) {
				doParse(currentNode);
			} else if (check.equals("images")) {
				doParse(currentNode);
			}
		}

		dataDAO.createProject(projectID, title, recordsPerImage, firstYCoord,
				recordHeight, numOfFields);
	}

	private void doParse(Node prevNode) throws SQLException {
		NodeList nodeList = prevNode.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node currentNode = nodeList.item(i);
			if (currentNode.getNodeName().equals("user")) {
				parseUser(currentNode);
			} else if (currentNode.getNodeName().equals("project")) {
				projectID++;
				parseProjects(currentNode);
			} else if (currentNode.getNodeName().equals("field")) {
				fieldID++;
				parseFields(currentNode);
			} else if (currentNode.getNodeName().equals("image")) {
				imageID++;
				parseImages(currentNode);
			} else if (currentNode.getNodeName().equals("record")) {
				recordID++;
				parseRecords(currentNode);
			}
		}
	}

	public void parseDOM() throws SQLException {
		Node root = DOM.getDocumentElement();
		db.startTransaction();
		db.getDataDAO().buildTables();
		projectID = 0;
		fieldID = 0;
		imageID = 0;
		recordID = 0;
		recordValueID = 0;
		for (int i = 0; i < root.getChildNodes().getLength(); i++) {
			Node currentNode = root.getChildNodes().item(i);
			if (currentNode.getNodeName().equals("users")) {
				doParse(currentNode);
			} else if (currentNode.getNodeName().equals("projects")) {
				doParse(currentNode);
			}
		}
		
		db.endTransaction(true);
		
		
		
	}

	/**
	 * TODO This still needs to be built, need to figure out how to open/read
	 * zip files.
	 * 
	 * @param file
	 * @throws ZipException
	 * @throws IOException
	 */
	public void openZip(File file) throws ZipException, IOException {

	}
}